#pragma once
#include <iostream>
#include <vector>
#include "Sem.hpp"
#include "Mutex.hpp"

static const int gcap = 5;

using namespace SemModule;
using namespace MutexModule;

template <typename T>
class RingQueue
{
public:
    RingQueue(int cap = gcap)
        : _cap(cap), _rq(cap), _blank_sem(cap), _p_step(0), _data_sem(0), _c_step(0)
    {
    }

    void Equeue(const T &in)
    {
        //生产者
        //1.申请空位置的信号量
        _blank_sem.P();
        {
            LockGuard lockguard(_pmutex);
            //2.生产
            _rq[_p_step]= in;
            //3.更新下标
            ++_p_step;
            //4.维持环形队列
            _p_step%=_cap;
        }
        _data_sem.V();
    }

    void Pop(T*out)
    {
        //消费者
        //1.申请数据信号量
        _data_sem.P();
        {
            LockGuard lockguard(_cmutex);
            //2.消费
            *out = _rq[_c_step];
            //3.更新下标
            ++_c_step;
            //4.维持环形队列
            _c_step%=_cap;
        }
        _blank_sem.V();
    }
   

private:
    std::vector<T> _rq;
    int _cap;

    Sem _blank_sem;
    int _p_step;

    Sem _data_sem;
    int _c_step;

    Mutex _cmutex;
    Mutex _pmutex;
};